package org.swift.mashup.engine.concurrency.execution;

import java.util.Map;
import java.util.Set;
import java.util.UUID;

import org.swift.mashup.engine.concurrency.ConcurrentContext;
import org.swift.mashup.engine.concurrency.agenda.ActionConfig;
import org.swift.mashup.engine.concurrency.agenda.ActionException;
import org.swift.mashup.engine.concurrency.agenda.ThreadMonitor;
import org.swift.mashup.engine.concurrency.memory.WorkingMemory;



public class ExecutionSession implements Runnable {
	private WorkingMemory memory;
	private Reasoner reasoner;	
	private ThreadMonitor monitor;
	private Map<String, Object> parameters;
	private ExecutionOutput output;
	private String sessionID;
	
	public Map<String, Object> getParameters() {
		return parameters;
	}

	public void setParameters(Map<String, Object> parameters) {
		this.parameters = parameters;
	}

	public ExecutionSession(RuleSet ruleset, ActionConfig config){
		this.sessionID = UUID.randomUUID().toString();
		this.memory = new WorkingMemory(ruleset.getMemoryTypes());
		this.reasoner = new Reasoner(ruleset,this.memory, null);		
		updateReasoner(reasoner, config);
	}
	public ExecutionSession(RuleSet ruleset, ActionConfig config, ConcurrentContext context){
		this.sessionID = context.getSessionID();
		this.memory = new WorkingMemory(ruleset.getMemoryTypes(), context.getWorkingDirectory() + "/workingMemory", this.sessionID,null, true);
		this.reasoner = new Reasoner(ruleset,this.memory, context);			
		updateReasoner(reasoner, config);
	}

	private void updateReasoner(Reasoner reasoner, ActionConfig config) {
		if(config != null && reasoner != null) {
			if(!config.isDurable()) {
				reasoner.setLaxErrors(true);
			}
			Integer timeout = config.getAgendaTimeout();
			if(timeout != null) {
				reasoner.setAgendaTimeout(timeout);
			}

            reasoner.setRateLimit( config.getRateLimit() );
		}
	}
	
	public WorkingMemory getWorkingMemory() {
		return memory;
	}


	public void setWorkingMemory(WorkingMemory memory) {
		this.memory = memory;
	}


	public Reasoner getReasoner() {
		return reasoner;
	}


	protected String getSessionID() {
		return sessionID.toString();
	}

	protected void setSessionID(String sessionID) {
		this.sessionID = sessionID;
	}

	public void setReasoner(Reasoner reasoner) {
		this.reasoner = reasoner;
	}

	public ThreadMonitor getMonitor() {
		return monitor;
	}


	public void setMonitor(ThreadMonitor monitor) {
		this.monitor = monitor;
	}

	
	public void run() {
		this.output = run(this.getParameters());		
	}
	
	public ExecutionOutput run(Map<String, ? extends Object> parameters) {		
		return this.reasoner.fire(parameters);
	}
	
	public ExecutionOutput getOutput() {
		return output;
	}

	public boolean hasErrors (){
		return getErrors().size() > 0;
	}
	
	public Set<ActionException> getErrors (){
		return this.reasoner.getErrors();
	}
}
